@echo off
:: chcp 437 >nul & graftabl 936 >nul
md tmp 2>nul
more +25 %0 > tmp\%~n0.cpp
if not "%1"=="debug" (
set coptimize=-O3 -msse -msse2 -ffast-math -D_SDL
set cxxoptimize=-Wno-invalid-offsetof -msse -msse2 -O3 -ftree-vectorize -funsafe-math-optimizations -ffast-math -fomit-frame-pointer -funsafe-loop-optimizations -D_SDL
) else (
set coptimize=-Wall -g -DDEBUG -D_SDL
set cxxoptimize=-Wno-invalid-offsetof -msse -msse2 -Wall -g -DDEBUG -D_SDL
)
g++ -c -o tmp\conxlat.o conxlat.cpp %cxxoptimize%
g++ -c -o tmp\%~n0.o tmp\%~n0.cpp %cxxoptimize%

g++ tmp\*.o -o %~n0.exe -Wl,-Bstatic -static-libgcc  -lluajit -lmingw32 -lm -lSDLmain -lSDL -lwinmm -mwindows -Wno-unused-result
:: rd /s /q tmp
if not "%1"=="debug" (
strip %~n0.exe
)
:: %~n0.exe

pause
goto :eof

// https://starcatcher.us/TPT/MingwLibraries.zip
#include <windows.h>
#include <SDL/SDL.h>
#include "../console-struct.h"
#include "../ascii-font-ex.h"

// #define XRES 200
// #define YRES 200
#define FMAP_LEN 120

#ifndef NT_SUCCESS
#define NT_SUCCESS(a) ((LONG)(a) >= 0)
#endif 

#if defined(_MSC_VER)
#define TRAP	__assume(0);
#elif defined(__GNUC__)
#define TRAP	__builtin_trap();
#else
#error
#endif

SDL_Surface *sdl_scrn;
fontdata_t *ascii_font_ptr = NULL;

void sdl_translate_map(_CHAR_DATA* text_buf, unsigned int * vid, int flags);

void sdl_blit(int x, int y, int w, int h, unsigned int *src, int pitch)
{
	unsigned *dst;
	int i, j;
	if (SDL_MUSTLOCK(sdl_scrn))
		if (SDL_LockSurface(sdl_scrn)<0)
			return;
	dst = (unsigned *)sdl_scrn->pixels+y*sdl_scrn->pitch/4+x;
	for (j = 0; j < h; j++)
	{
		for (i = 0; i < w; i++)
			dst[i] = src[i];
		dst += sdl_scrn->pitch/4;
		src += pitch/4;
	}
	if (SDL_MUSTLOCK(sdl_scrn))
		SDL_UnlockSurface(sdl_scrn);
	SDL_UpdateRect(sdl_scrn,0,0,0,0);
}

int main (int argc, char** argv)
{
	if (argv[1] == NULL)
	{
		fprintf(stderr, "No arguments");
		exit(1);
	}
	
	HMODULE hNtdll = GetModuleHandle("ntdll.dll");
	if (hNtdll == NULL)
	{
		if (GetLastError() == ERROR_MOD_NOT_FOUND)
			hNtdll = LoadLibrary("ntdll.dll");
		if (hNtdll == NULL)
			exit(1);
	}

	unsigned * vid = (unsigned*)calloc(XRES*YRES, sizeof(unsigned));
	HANDLE hMapFile;
	_CHAR_DATA * pMapBuffer;
	
	if (SDL_Init(SDL_INIT_VIDEO)<0)
	{
		fprintf(stderr, "Initializing SDL: %s\n", SDL_GetError());
		free(vid);
		exit(1);
	}

	atexit(SDL_Quit);

	do
	{
		char fm_name[FMAP_LEN] = "MYCON_";
		size_t fm_pfxl = strlen(fm_name);
		size_t fm_argl = FMAP_LEN - 1 - fm_pfxl;
		strncpy(fm_name + fm_pfxl, argv[1], fm_argl);
		fm_name[FMAP_LEN-1] = '\0';
		
		hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, TRUE, fm_name);
	}
	while (0);

	ascii_font_ptr = (fontdata_t *)calloc(FONT_NUM_CHARS, sizeof(intptr_t));

	if (hMapFile == NULL || ascii_font_ptr == NULL)
	{
		free(vid);
		if (hMapFile != NULL)
			CloseHandle(hMapFile);
		exit(1);
	}

	for (int i = 0; i < 95; i++)
		ascii_font_ptr[i+32] = (fontdata_t)ascii_font[i];

	struct _STATUS_DATA_1 {
		int64_t tHandle;		// 8-byte
		int64_t tHandleMutex;	// 8-byte
		int statusf[2];
	} *lpStat;
	
	pMapBuffer = (_CHAR_DATA *) MapViewOfFile(
		hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, XCHRS * YCHRS * sizeof(_CHAR_DATA) + sizeof(_STATUS_DATA_1) );
	
	if (pMapBuffer == NULL)
	{
		free(ascii_font_ptr);
		free(vid);
		CloseHandle(hMapFile);
		exit(1);
	}
	else
	{
		lpStat = (_STATUS_DATA_1 *)(&(pMapBuffer[XCHRS * YCHRS]));
		int __stdcall (*fAlertThread)(HANDLE) = (int __stdcall (*)(HANDLE)) GetProcAddress(hNtdll, "NtAlertThread");
		void __stdcall (*fRaiseStatus)(int) = (void __stdcall (*)(int)) GetProcAddress(hNtdll, "RtlRaiseStatus");

#ifdef __GNUC__
		if (__sync_bool_compare_and_swap(&(lpStat->statusf[0]), 0, 1))
#else
		if (InterlockedCompareExchange(&(lpStat->statusf[0]), 1, 0) == 0)
#endif
		{
			if ((HANDLE)(lpStat->tHandle) != NULL && fAlertThread != NULL && fRaiseStatus != NULL)
			{
				int status = fAlertThread((HANDLE)(lpStat->tHandle));
				if (!NT_SUCCESS(status))
				{
					fRaiseStatus(status); TRAP
				}
				// lpStat->status = 2;
			}
			else
			{
				MessageBox (HWND_DESKTOP, "NTAPI function not found", NULL, MB_ICONERROR);
				ExitProcess(1);
			}
		}
	}
	
	sdl_scrn = SDL_SetVideoMode(XRES, YRES, 32, SDL_SWSURFACE);
	if (!sdl_scrn)
	{
		fprintf(stderr, "Creating window: %s\n", SDL_GetError());
		exit(1);
	}

	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
	SDL_EnableUNICODE(1);
	
	bool is_quit = false;
	SDL_Event event;

#ifdef DEBUG
	::AllocConsole();
	freopen("CON", "w", stdout);
	freopen("CON", "w", stderr);
#endif

	do {
		bool sdl_redrawn = false;

		while (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
				is_quit = true;
			else 
			{
				if (event.type == SDL_VIDEOEXPOSE)
					sdl_redrawn = true;
#ifdef DEBUG
				printf("%d\n", event.type);
#endif
			}
		}
		
		if (lpStat->statusf[1] & 0x1)
			is_quit = true;

		SDL_Delay(20);
		
		sdl_translate_map(pMapBuffer, vid, 0);
		sdl_blit(0, 0, XRES, YRES, vid, XRES*4);
	}
	while (!is_quit);

#ifdef DEBUG
	::FreeConsole();
#endif

	free(ascii_font_ptr);
	free(vid);
	
	UnmapViewOfFile(pMapBuffer);
	
	CloseHandle(hMapFile);

	return 0;
}